package com.dzl.userwx;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dzl.base.controller.BaseController;
import com.dzl.base.pojo.BaseData;
import com.dzl.base.service.BaseDataService;
import com.dzl.card.service.WelfareCardTypeService;
import com.dzl.constant.SmsTypeConstant;
import com.dzl.enterprise.pojo.WelfareEnterprise;
import com.dzl.enterprise.service.WelfareEnterpriseService;
import com.dzl.userwx.pojo.WelfareUserWx;
import com.dzl.userwx.pojo.dto.WelfareUserWxAddDto;
import com.dzl.userwx.pojo.vo.WelfareUserCommonVo;
import com.dzl.userwx.service.WelfareUserWxService;
import com.dzl.util.*;
import com.dzl.util.wx.WxConfig;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import tk.mybatis.mapper.entity.Example;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.AlgorithmParameters;
import java.security.Security;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;

/**
 * 小程序用户表相关操作
 * @author ChenLong
 * @since 2021-05-19 18:41:26
 **/
@Slf4j
@RestController
@RequestMapping("welfareUserWx")
public class WelfareUserWxController extends BaseController {

    @Autowired
    private WelfareUserWxService welfareUserWxService;
    @Autowired
    private WelfareCardTypeService welfareCardTypeService;
    @Autowired
    private BaseDataService baseDataService;
    @Autowired
    private WelfareEnterpriseService welfareEnterpriseService;

    // token保存时间（分钟）todo：pro
    private static final int TOKEN_TIMES_MINUTE = 60 * 24 * 3;

    /**
     * 微信登录
     * @param code 微信code
     * @param enterpriseId 企业id
     * @return com.dzl.util.JsonResult
     * @author ChenLong
     * @since 2021-05-17 09:34:50
     **/
    @GetMapping(value = "wxLogin")
    public JsonResult<JSONObject> wxLogin(String code, Integer enterpriseId) {
        log.info("wxLogin in");
        if(EmptyUtils.isEmpty(code)){
            return JsonResult.paramErrWithMsg("code不能传空");
        }
        if(enterpriseId==null){
            return JsonResult.paramErrWithMsg("企业ID不能传空");
        }
        WelfareEnterprise welfareEnterprise = welfareEnterpriseService.selectByPrimaryKey(enterpriseId);
        if(EmptyUtils.isEmpty(welfareEnterprise) || EmptyUtils.isEmpty(welfareEnterprise.getAppid()) || EmptyUtils.isEmpty(welfareEnterprise.getAppsecret())
                || EmptyUtils.isEmpty(welfareEnterprise.getMchId()) || EmptyUtils.isEmpty(welfareEnterprise.getMchKey())){
            return JsonResult.failWithMsg("微信登录异常:缺少小程序独立部署配置参数");
        }
        String url = WxConfig.XCX_OAUTH_URL + "?appid=" + welfareEnterprise.getAppid() + "&secret=" + welfareEnterprise.getAppsecret() + "&js_code=" + code + "&grant_type=authorization_code";
        //String url = WxConfig.XCX_OAUTH_URL + "?appid=" + WxConfig.WX_XCX_APPID + "&secret=" + WxConfig.WX_XCX_SECRET + "&js_code=" + code + "&grant_type=authorization_code";
        String result = HttpUtil.sendGet(url, "UTF-8");
        log.info("wxLogin result: " + result);
        JSONObject jsonObject = (JSONObject) JSON.parse(result);
        if (EmptyUtils.isEmpty(jsonObject) || EmptyUtils.isEmpty(jsonObject.getString("openid"))) {
            return new JsonResult<>(null, Integer.parseInt(jsonObject.getString("errcode")), jsonObject.getString("errmsg"));
        }
        // 判断该用户是否是第一次登录
        String openId = jsonObject.getString("openid");
        Example welfareUserWxExample = new Example(WelfareUserWx.class);
        welfareUserWxExample.createCriteria().andEqualTo("openId", openId);
        WelfareUserWx welfareUserWxResult = welfareUserWxService.selectOneByExample(welfareUserWxExample);
        if (EmptyUtils.isEmpty(welfareUserWxResult) || EmptyUtils.isEmpty(welfareUserWxResult.getOpenId())) {
            jsonObject.put("is_first_login", 0);
            // 如果是第一次登录，添加该小程序用户(openId)
            WelfareUserWx welfareUserWx = new WelfareUserWx();
            welfareUserWx.setOpenId(openId);
            welfareUserWx.setCreateTime(new Date());
            welfareUserWx.setStatus(1);
            welfareUserWx.setEnterpriseId(enterpriseId);
            int resCode = welfareUserWxService.insertSelective(welfareUserWx);
            if (resCode < 1) {
                return JsonResult.failWithMsg("登陆失败");
            }
            String token = TokenUtil.generateToken(welfareUserWx.getId());
            RedisUtil.set(token, JSONObject.toJSONString(welfareUserWx), 60 * TOKEN_TIMES_MINUTE);//缓存7天
            jsonObject.put("token", token);
            jsonObject.put("userInfo", welfareUserWx);
        } else {
            jsonObject.put("is_first_login", 1);
            String token = TokenUtil.generateToken(welfareUserWxResult.getId());
            RedisUtil.set(token, JSONObject.toJSONString(welfareUserWxResult), 60 * TOKEN_TIMES_MINUTE);//缓存7天
            jsonObject.put("token", token);
            jsonObject.put("userInfo", welfareUserWxResult);
        }
        Map<String, Object> resMap = welfareUserWxService.wxVerify(openId);
        jsonObject.put("reg_info", resMap);
        return JsonResult.success(jsonObject);
    }

    /**
     * 登录校验（校验是否登录，是否绑卡，是否设置支付密码）
     * @return com.dzl.util.JsonResult
     * @author ChenLong
     * @since 2021-05-17 09:35:11
     **/
    @GetMapping(value = "wxVerify")
    public JsonResult<Object> wxVerify(String openId) {
        log.info("wxVerify in openId: " + openId);
        Map<String, Object> resMap = welfareUserWxService.wxVerify(openId);
        if (resMap.get("code").equals(1)) {
            return JsonResult.success(resMap.get("data"));
        } else {
            return JsonResult.failWithMsg(resMap.get("msg").toString());
        }
    }

    /**
     * 获取用户手机号信息
     * @param sessionKey sessionKey
     * @param encryptedData encryptedData
     * @param iv iv
     * @return com.alibaba.fastjson.JSONObject
     * @date 2020/12/14 19:33
     * @author lishunxing
     */
    @GetMapping("/getPhone")
    public JsonResult getPhone(String sessionKey, String encryptedData, String iv) {
        log.info("getPhoneNumber encrypdata: " + encryptedData);
        log.info("getPhoneNumber ivdata: " + iv);
        log.info("getPhoneNumber sessionkey: " + sessionKey);
        byte[] dataByte = Base64.decode(encryptedData);
        byte[] keyByte = Base64.decode(sessionKey);
        byte[] ivByte = Base64.decode(iv);

        int base = 16;
        if (keyByte.length % base != 0) {
            int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
            byte[] temp = new byte[groups * base];
            Arrays.fill(temp, (byte) 0);
            System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
            keyByte = temp;
        }
        try {
            // 初始化
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);
            byte[] resultByte = cipher.doFinal(dataByte);
            log.info("getPhoneNumber resultByte: " + resultByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, "UTF-8");
                return JsonResult.success(result);
            } else {
                return JsonResult.fail();
            }
        } catch (Exception e) {
            return JsonResult.failWithMsg(e.getMessage());
        }
    }

    /**
     * 通过openId获取用户信息
     * @param openId 微信openId
     * @return com.dzl.util.JsonResult<java.lang.Object>
     * @author ChenLong
     * @since 2021-05-17 17:32:38
     **/
    @GetMapping(value = "getWxUserInfo")
    public JsonResult<WelfareUserWx> getWxUserInfo(String openId) {
        log.info("getWxUserInfo in openId: " + openId);
        return JsonResult.success(welfareUserWxService.getWxUserInfo(openId));
    }

    /**
     * 获取用户综合信息（订单数量、卡密数量）
     * @return com.dzl.util.JsonResult<java.lang.Object>
     * @author ChenLong
     * @since 2021-05-17 17:32:38
     **/
    @GetMapping(value = "getWxUserCommonInfo")
    public JsonResult<WelfareUserCommonVo> getWxUserCommonInfo() {
        log.info("getWxUserCommonInfo in ");
        Integer userId = getWxUserInfo().getId();
        return JsonResult.success(welfareUserWxService.getWxUserCommonInfo(userId));
    }

    /**
     * 设置支付密码
     * @param ppwd 支付密码
     * @return com.dzl.util.JsonResult<java.lang.Object>
     * @author ChenLong
     * @date 2021-05-27 12:36:22
     **/
    @PostMapping("addPayPassword")
    public JsonResult<Integer> addPayPassword(String ppwd) {
        log.info("addPayPassword in");
        Integer userId = getWxUserInfo().getId();
        // 新密码不能为空
        if (EmptyUtils.isEmpty(ppwd)) {
            return JsonResult.paramErrWithMsg("请输入新密码");
        }
        int resCode = welfareUserWxService.addPayPassword(userId, ppwd);
        if (resCode > 0) {
            return JsonResult.success();
        } else {
            return JsonResult.failWithMsg("设置支付密码失败");
        }
    }

    /**
     * 校验支付密码
     * @param ppwd 支付密码
     * @return com.dzl.util.JsonResult<java.lang.Object>
     * @author ChenLong
     * @date 2021-05-27 12:38:32
     **/
    @PostMapping("validatePayPassword")
    public JsonResult<Integer> validatePayPassword(String ppwd) {
        log.info("validatePayPassword in");
        Integer userId = getWxUserInfo().getId();
        if (EmptyUtils.isEmpty(ppwd)) {
            return JsonResult.paramErrWithMsg("支付密码不能为空");
        }
        Example welfareUserWxExample = new Example(WelfareUserWx.class);
        welfareUserWxExample.createCriteria().andEqualTo("id", userId);
        WelfareUserWx welfareUserWx = welfareUserWxService.selectOneByExample(welfareUserWxExample);
        if (EmptyUtils.isEmpty(welfareUserWx)) {
            return JsonResult.failWithMsg("支付密码校验错误");
        }
        if (welfareUserWx.getPayPassword() == null || EmptyUtils.isEmpty(welfareUserWx.getPayPassword())) {
            return JsonResult.failWithMsg("请设置支付密码");
        }
        String decPpwd = PasswordUtil.AESDecrypt(welfareUserWx.getPayPassword());
        if (!ppwd.equals(decPpwd)) {
            return JsonResult.failWithMsg("支付密码错误");
        }
        return JsonResult.success();
    }

    /**
     * 修改支付密码
     * @param jsonParams 用户id、支付密码，手机号、验证码
     * @return com.dzl.util.JsonResult
     * @author ChenLong
     * @since 2021-05-17 09:34:34
     **/
    @PostMapping("updatePayPassword")
    public JsonResult<Integer> updatePayPassword(@RequestBody JSONObject jsonParams) {
        log.info("updatePayPassword in");
        Integer userId = getWxUserInfo().getId();
        String ppwd = jsonParams.getString("ppwd");
        String phone = jsonParams.getString("phone");
        String code = jsonParams.getString("code");
        // 电话号码不能为空
        if (EmptyUtils.isEmpty(phone)) {
            return new JsonResult<>(null, HttpCode.MOBILE_NULL_ERR);
        }
        // 新密码不能为空
        if (EmptyUtils.isEmpty(ppwd)) {
            return JsonResult.paramErrWithMsg("请输入新密码");
        }
        // 获取session验证码
        // todo：pro SmsTypeConstant.SMS_TYPE_CHANGE_PAYPASSWORD
        String sessionCode = (String) RedisUtil.get(phone + ":" + SmsTypeConstant.SMS_TYPE_BIND_NORMAL);
        // 验证码校验
        if (EmptyUtils.isEmpty(sessionCode) || !code.equals(sessionCode)) {
            return JsonResult.paramErrWithMsgAndCode(1027, "验证码错误，请重新获取");
        }
        int resCode = welfareUserWxService.updatePayPassword(userId, ppwd);
        if (resCode > 0) {
            return JsonResult.success();
        } else {
            return JsonResult.failWithMsg("操作失败");
        }
    }

    /**
     * 修改电话号码
     * @param jsonParams 用户id、原手机号码、原手机号的验证码、新手机号、新手机号的验证码
     * @return com.dzl.util.JsonResult<java.lang.Object>
     * @author ChenLong
     * @since 2021-05-20 11:00:11
     **/
    @PostMapping("updatePhoneNumber")
    public JsonResult<Integer> updatePhoneNumber(@RequestBody JSONObject jsonParams) {
        log.info("updatePhoneNumber in jsonParams: " + jsonParams);
        Integer userId = getWxUserInfo().getId();
        // 电话号码不能为空（此处不对老电话号码做校验）
        if (EmptyUtils.isEmpty(jsonParams.getString("newPhoneNumber"))) {
            return JsonResult.paramErrWithMsgAndCode(1028,"请输入新手机号");
        }
        if (EmptyUtils.isEmpty(jsonParams.getString("newPhoneCode"))) {
            return JsonResult.paramErrWithMsgAndCode(1029,"请输入新手机验证码");
        }
        if (EmptyUtils.isEmpty(jsonParams.getString("oldPhoneNumber"))) {
            return JsonResult.paramErrWithMsgAndCode(1026, "请输入原手机号");
        }
        if (EmptyUtils.isEmpty(jsonParams.getString("oldPhoneCode"))) {
            return JsonResult.paramErrWithMsgAndCode(1027, "请输入原手机验证码");
        }
        String oldPhoneNumber = jsonParams.getString("oldPhoneNumber");
        String oldPhoneCode = jsonParams.getString("oldPhoneCode");
        String newPhoneNumber = jsonParams.getString("newPhoneNumber");
        String newPhoneCode = jsonParams.getString("newPhoneCode");
        if (oldPhoneNumber.equals(newPhoneNumber)){
            return JsonResult.paramErrWithMsgAndCode(1027, "相同的手机号");
        }
        // 获取session验证码
        // todo：pro SmsTypeConstant.SMS_TYPE_CHANGE_PHONE_NUMBER
        String sessionCodeOldPhone = (String) RedisUtil.get(oldPhoneNumber + ":" + SmsTypeConstant.SMS_TYPE_BIND_NORMAL);
        // 验证码校验
        if (EmptyUtils.isEmpty(sessionCodeOldPhone)) {
            return JsonResult.paramErrWithMsgAndCode(1027, "请输入原手机验证码");
        }
        if (!oldPhoneCode.equals(sessionCodeOldPhone)) {
            return JsonResult.paramErrWithMsgAndCode(1027, "原手机号验证码错误");
        }
        // 校验新手机号验证码
        // 获取session验证码
        // todo：pro SmsTypeConstant.SMS_TYPE_CHANGE_PHONE_NUMBER
        String sessionCodeNewPhone = (String) RedisUtil.get(newPhoneNumber + ":" + SmsTypeConstant.SMS_TYPE_BIND_NORMAL);
        // 验证码校验
        if (EmptyUtils.isEmpty(sessionCodeNewPhone)) {
            return JsonResult.paramErrWithMsgAndCode(1029,"请输入新手机验证码");
        }
        if (!newPhoneCode.equals(sessionCodeNewPhone)) {
            return JsonResult.paramErrWithMsgAndCode(1029,"新手机号验证码错误");
        }
        // 校验该手机号是否已被绑定
        WelfareUserWx welfareUserWxSelect = new WelfareUserWx();
        welfareUserWxSelect.setPhone(newPhoneNumber);
        Integer phoneCount = welfareUserWxService.selectCount(welfareUserWxSelect);
        if (phoneCount > 0) {
            return JsonResult.paramErrWithMsgAndCode(1028,"新手机号已被绑定");
        }
        // 修改手机号
        return JsonResult.success(welfareUserWxService.updatePhoneNumber(userId, newPhoneNumber));
    }

    /**
     * 添加保存微信用户信息
     * @param welfareUserWxAddDto 微信用户基本信息
     * @return com.dzl.util.JsonResult<java.lang.Integer>
     * @author ChenLong
     * @date 2021-06-17 19:27:22
     **/
    @PostMapping("addWxUserBaseInfo")
    public JsonResult<Integer> addWxUserBaseInfo(@RequestBody WelfareUserWxAddDto welfareUserWxAddDto) {
        log.info("addWxUserBaseInfo in : " + welfareUserWxAddDto);
        if (EmptyUtils.isEmpty(welfareUserWxAddDto)) {
            return JsonResult.paramErrWithMsg("参数错误");
        }
        Integer userId = getWxUserInfo().getId();
        WelfareUserWx welfareUserWx = new WelfareUserWx();
        welfareUserWx.setId(userId);
        welfareUserWx.setUpdateTime(new Date());
        if (EmptyUtils.isNotEmpty(welfareUserWxAddDto.getOpenId())) {
            welfareUserWx.setOpenId(welfareUserWxAddDto.getOpenId());
        }
        if (EmptyUtils.isNotEmpty(welfareUserWxAddDto.getUserName())) {
            welfareUserWx.setUserName(welfareUserWxAddDto.getUserName());
        }
        if (EmptyUtils.isNotEmpty(welfareUserWxAddDto.getUnionId())) {
            welfareUserWx.setUnionId(welfareUserWxAddDto.getUnionId());
        }
        if (EmptyUtils.isNotEmpty(welfareUserWxAddDto.getAvatar())) {
            welfareUserWx.setAvatar(welfareUserWxAddDto.getAvatar());
        }
        if (EmptyUtils.isNotEmpty(welfareUserWxAddDto.getSex())) {
            welfareUserWx.setSex(welfareUserWxAddDto.getSex());
        }
        if (EmptyUtils.isNotEmpty(welfareUserWxAddDto.getBirthday())) {
            welfareUserWx.setBirthday(welfareUserWxAddDto.getBirthday());
        }
        if (EmptyUtils.isNotEmpty(welfareUserWxAddDto.getCountry())) {
            welfareUserWx.setCountry(welfareUserWxAddDto.getCountry());
        }
        if (EmptyUtils.isNotEmpty(welfareUserWxAddDto.getProvince())) {
            welfareUserWx.setProvince(welfareUserWxAddDto.getProvince());
        }
        if (EmptyUtils.isNotEmpty(welfareUserWxAddDto.getCity())) {
            welfareUserWx.setCity(welfareUserWxAddDto.getCity());
        }
        if (EmptyUtils.isNotEmpty(welfareUserWxAddDto.getArea())) {
            welfareUserWx.setArea(welfareUserWxAddDto.getArea());
        }
        if (EmptyUtils.isNotEmpty(welfareUserWxAddDto.getAddress())) {
            welfareUserWx.setAddress(welfareUserWxAddDto.getAddress());
        }
        int resCode = welfareUserWxService.updateByPrimaryKeySelective(welfareUserWx);
        if (resCode > 0) {
            return JsonResult.success();
        } else {
            return JsonResult.failWithMsg("操作失败");
        }
    }

    /**
     * 通过用户id查询是否有分类入口查看权限
     * @date 2021/12/30 11:04
     * @author liuguanjun
     * return :1有权限 0无权限
     */
    @GetMapping(value = "selectShowClassifyEntry")
    public JsonResult<Integer> selectShowClassifyEntryByUserId() {
        //查询是否绑定过分类入口商品的福利卡
        Integer count = welfareCardTypeService.selectShowClassifyEntryByUserId(getWxUserId());
        if(count>0){
            //查询分类入口图片是否有值
            BaseData baseData3 =  baseDataService.selectByPrimaryKey(3);  //分类入口图片
            if(EmptyUtils.isNotEmpty(baseData3) && EmptyUtils.isNotEmpty(baseData3.getRemark()) && EmptyUtils.isNotEmpty(baseData3.getRemark().trim())){
                count = 1;
            }else{
                count = 0;
            }
        }
        return JsonResult.success(count);
    }
}
